package com.zhang.bingmei_incomeexpenditure.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.zhang.bingmei_incomeexpenditure.config.CustomColumnWidthHandler;
import com.zhang.bingmei_incomeexpenditure.config.ForceNewRowMergeStrategy;
import com.zhang.bingmei_incomeexpenditure.entity.Utils.IECommUtil;
import com.zhang.bingmei_incomeexpenditure.entity.commom.BeanCopyUtil;
import com.zhang.bingmei_incomeexpenditure.entity.commom.R;
import com.zhang.bingmei_incomeexpenditure.entity.ie.CodeCityNameAndYearVO;
import com.zhang.bingmei_incomeexpenditure.entity.ie.IncomeExpenditurePageDTO;
import com.zhang.bingmei_incomeexpenditure.entity.ie.selectNew.SelectDoubleResult;
import com.zhang.bingmei_incomeexpenditure.entity.ie.selectNew.SelectDoubleVO;
import com.zhang.bingmei_incomeexpenditure.entity.ie.updateNew.UpdateDoubleDTO;
import com.zhang.bingmei_incomeexpenditure.entity.ie.updateNew.UpdateDoubleVO;
import com.zhang.bingmei_incomeexpenditure.service.IncomeExpenditureService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 资金管理-收支情况
 * @Author: zsj
 * @Date: 2025/10/14 14:33
 */
@Slf4j
@RestController
@Api(tags = "收支情况模块相关接口")
@RequestMapping("/incomeExpenditure")
@RequiredArgsConstructor
public class IncomeExpenditureController {

    private final IncomeExpenditureService incomeExpenditureService;

    /**
     * 获取当前用户管辖市辖区信息: code + distinct + year
     *
     * @param dto
     * @return
     */
    @ApiOperation(value = "1-获取当前用户管辖市辖区")
    @ApiOperationSupport(author = "zsj", order = 1)
    @PostMapping("/getDistricts")
    public R<List<CodeCityNameAndYearVO>> getDistricts(@RequestBody @Validated IncomeExpenditurePageDTO dto) {
        List<CodeCityNameAndYearVO> allCities = incomeExpenditureService.getAllDistrict(dto);
        // 处理可能的空集合
        allCities = allCities == null ? Collections.emptyList() : allCities;
        return R.ok(allCities, allCities.size());
    }

    //获取首页数据（Double）
    @ApiOperation(value = "2-获取首页数据")
    @ApiOperationSupport(author = "zsj", order = 2)
    @PostMapping("/getIndex")
    public R<List<SelectDoubleResult>> getIndexViewIsDouble(@RequestBody @Validated IncomeExpenditurePageDTO dto) {
        SelectDoubleResult incomeExpenditureResult = incomeExpenditureService.getAllIEData(dto);
        Map<String, Object> result = new HashMap<>(2);
        result.put("dataList", incomeExpenditureResult);       // 原收支情况列表(含合计)

        Boolean updateFlag = IECommUtil.isUpdateButton();
        result.put("updateFlag", updateFlag);

        log.debug("getAllIEData(): 获取收支情况列表，出参：result:{}", result);
        int size = incomeExpenditureResult.getSelectDoubleResults().size();
        return R.ok(result, size);
    }

    //修改（Double）
    @ApiOperation(value = "3-编辑（修改+新增）")
    @ApiOperationSupport(author = "zsj", order = 3)
    @PostMapping("/update")
    public R<List<UpdateDoubleVO>> updateNew(@RequestBody @Validated List<UpdateDoubleDTO> dataList) {
        List<UpdateDoubleVO> updateDoubleVOS = incomeExpenditureService.batchUpdateIncomeExpenditureDataLong2(dataList);

        // 2. 用Map封装“列表数据”和“updateFlag”
        Map<String, Object> result = new HashMap<>(2);
        result.put("dataList", updateDoubleVOS);       // 原收支情况列表

        Boolean updateFlag = IECommUtil.isUpdateButton();
        result.put("updateFlag", updateFlag);

        log.debug("updateIncomeExpenditureList(): 获取收支情况列表，出参：result:{}", result);
        return R.ok(result);
    }

    //导出（Double）
    @ApiOperation(value = "4-导出收支情况.xlsx表")
    @ApiOperationSupport(author = "zsj", order = 4)
    @PostMapping("/export")
    void exportExcel(@RequestBody @Validated IncomeExpenditurePageDTO dto, HttpServletResponse response) throws Exception {
        //获取数据
        SelectDoubleResult oldData = incomeExpenditureService.getAllIEData(dto);
        //数据封装
        SelectDoubleResult exportResultData = new SelectDoubleResult();
        List<SelectDoubleVO> list = BeanCopyUtil.copyListToList(oldData.getSelectDoubleResults(), SelectDoubleVO.class);
        exportResultData.setSelectDoubleResults(list);
        exportResultData.setSelectDoubleSum(oldData.getSelectDoubleSum());

        String fileName = "file/fillexcel/IE-template2.xlsx";
        // 从classpath根目录读取模板文件（编译后resources目录下的文件会在根目录）
        InputStream templateStream = getClass().getClassLoader().getResourceAsStream(fileName);

        if (templateStream == null) {
            log.error("收支情况导出模板文件不存在: {}，请确保文件位于 vector-module/vector-admin/src/main/resources/ 目录下", fileName);
            throw new RuntimeException("收支情况导出模板文件不存在: " + fileName);
        }

        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment; filename=example.xlsx");
        ServletOutputStream outputStream = response.getOutputStream();
        // ---------- 1. 准备 Map（非列表部分） ----------
        Map<String, Object> dataMap = new HashMap<>();

        IncomeExpenditurePageDTO formatDto = IECommUtil.getDTO(dto);
        dataMap.put("startDate", formatDto.getStartDateStr());
        dataMap.put("endDate", formatDto.getEndDateStr());
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> sumMap = mapper.convertValue(exportResultData.getSelectDoubleSum(), Map.class);

        dataMap.putAll(sumMap);
        // ---------- 2. 准备 List（列表部分） ----------
        List<SelectDoubleVO> detailList = exportResultData.getSelectDoubleResults();
        // ---------- 3. 写出 ----------

        Map<Integer, Integer> columnWidthMap = new HashMap<>();
        columnWidthMap.put(0, 22);  // 0: 市辖区
        columnWidthMap.put(1, 10);  // 1: 年度
        columnWidthMap.put(2, 16);  // 2: 市级下拨经费
        columnWidthMap.put(3, 16);  // 3: 区级配套经费
        columnWidthMap.put(4, 22);  // 4: 其他（财政专项、单位自筹等）
        columnWidthMap.put(5, 16);  // 5: 经费来源合计
        columnWidthMap.put(6, 28);  // 6: 购置、维修、维护“防蚊、防蚊蝇”设施支出
        columnWidthMap.put(7, 22);  // 7: 购买消杀设备、药品支出
        columnWidthMap.put(8, 26);  // 8: 病媒生物防制相关宣传费、印刷费
        columnWidthMap.put(9, 30);  // 9: 组织专家开展区内病媒防制工作研讨等支出
        columnWidthMap.put(10, 24); // 10: 购买第三方病媒防制服务支出
        columnWidthMap.put(11, 22); // 11: 其他不属于上述用途的支出
        columnWidthMap.put(12, 18); // 12: 已实际完成支付合计
        columnWidthMap.put(13, 18); // 13: 被收回的市级下拨经费
        columnWidthMap.put(14, 18); // 14: 被收回的区级配套经费

        CustomColumnWidthHandler columnWidthHandler = new CustomColumnWidthHandler(columnWidthMap); // 自定义列宽处理器

        //创建自定义合并规则（这里注意版本问题！！！被坑了）
        ForceNewRowMergeStrategy mergeStrategy = new ForceNewRowMergeStrategy(0, new int[]{0});

        ExcelWriter excelWriter = EasyExcel.write(outputStream)
                .withTemplate(templateStream)
                .excelType(ExcelTypeEnum.XLSX)
                .build();
        //这一行必须加：否则会遇见占位符覆盖的现象，这个比较恶心，会导致最后一行合计无法正常显示
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        WriteSheet writeSheet = EasyExcel.writerSheet()
                //应用合并规则
                .registerWriteHandler(mergeStrategy)
                .registerWriteHandler(columnWidthHandler) // 注册列宽处理器
                .build();
        // 关键：分两次 fill
        // 合计、日期等普通占位符
        excelWriter.fill(dataMap, writeSheet);
        // 列表占位符  如果是多个的话，就会用到这个FillWrapper，我这是为了做演示，就给你加了一下，对应的模板也对应加了一下
        excelWriter.fill(new FillWrapper("data", detailList), fillConfig, writeSheet);
        excelWriter.finish();
    }
}

    /**
     * 导出（Double）
     * @param dto
     * @param response
     * @throws Exception
     */
/*
    //导出（Double）
    @ApiOperationSupport(author = "zsj")
    @ApiOperation("导出收支情况列表")
    @PreAuthorize("@el.check('incomingOutgoings:edit')")
    @PostMapping("/export")
    void exportExcel(@RequestBody @Validated IncomeExpenditurePageDTO dto, HttpServletResponse response) throws Exception {
        //获取数据
        SelectDoubleResult oldData = incomeExpenditureService.getAllIEData(dto);
        //数据封装
        SelectDoubleResult exportResultData = new SelectDoubleResult();
        List<SelectDoubleVO> list = BeanCopyUtil.copyListToList(oldData.getSelectDoubleResults(), SelectDoubleVO.class);
        exportResultData.setSelectDoubleResults(list);
        exportResultData.setSelectDoubleSum(oldData.getSelectDoubleSum());
        log.debug("exportIncomeExpenditure(): 导出收支情况列表，入参：dto:{}",dto);
        log.debug("exportIncomeExpenditure(): 导出收支情况列表，查询数据：oldData:{}",oldData);
        log.debug("exportIncomeExpenditure(): 导出收支情况列表，导出数据：exportResultData:{}",exportResultData);

        String fileName = "IE-template2.xlsx";
        InputStream templateStream = getClass().getClassLoader().getResourceAsStream(File.separatorChar + fileName);
        int flag = -1;
        if ((templateStream == null || templateStream.available() <= 0) && flag == -1 ) {
            //这里如果获取不到的话，可以使用仓库相对路径去读取
            templateStream = this.getClass().getClassLoader().getResourceAsStream("vector-module/vector-admin/src/main/resources/IE-template.xlsx");
            if(templateStream == null || templateStream.available() <= 0) flag = 1;
        }
        //双判文件
        if ((templateStream == null || templateStream.available() <= 0) && flag == 1) {
            log.error("收支情况导出模板文件不存在: {}", fileName);
            throw new RuntimeException("收支情况导出模板文件不存在");
        }

        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment; filename=example.xlsx");
        ServletOutputStream outputStream = response.getOutputStream();
        // ---------- 1. 准备 Map（非列表部分） ----------
        Map<String, Object> dataMap = new HashMap<>();

        IncomeExpenditurePageDTO formatDto = IECommUtil.getDTO(dto);
        dataMap.put("startDate", formatDto.getStartDateStr());
        dataMap.put("endDate", formatDto.getEndDateStr());
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> sumMap = mapper.convertValue(exportResultData.getSelectDoubleSum(), Map.class);

        dataMap.putAll(sumMap);
        // ---------- 2. 准备 List（列表部分） ----------
        List<SelectDoubleVO> detailList = exportResultData.getSelectDoubleResults();
        // ---------- 3. 写出 ----------

        Map<Integer, Integer> columnWidthMap = new HashMap<>();
        columnWidthMap.put(0, 22);  // 0: 市辖区
        columnWidthMap.put(1, 10);  // 1: 年度
        columnWidthMap.put(2, 16);  // 2: 市级下拨经费
        columnWidthMap.put(3, 16);  // 3: 区级配套经费
        columnWidthMap.put(4, 22);  // 4: 其他（财政专项、单位自筹等）
        columnWidthMap.put(5, 16);  // 5: 经费来源合计
        columnWidthMap.put(6, 28);  // 6: 购置、维修、维护“防蚊、防蚊蝇”设施支出
        columnWidthMap.put(7, 22);  // 7: 购买消杀设备、药品支出
        columnWidthMap.put(8, 26);  // 8: 病媒生物防制相关宣传费、印刷费
        columnWidthMap.put(9, 30);  // 9: 组织专家开展区内病媒防制工作研讨等支出
        columnWidthMap.put(10, 24); // 10: 购买第三方病媒防制服务支出
        columnWidthMap.put(11, 22); // 11: 其他不属于上述用途的支出
        columnWidthMap.put(12, 18); // 12: 已实际完成支付合计
        columnWidthMap.put(13, 18); // 13: 被收回的市级下拨经费
        columnWidthMap.put(14, 18); // 14: 被收回的区级配套经费

        CustomColumnWidthHandler columnWidthHandler = new CustomColumnWidthHandler(columnWidthMap); // 自定义列宽处理器

        //创建自定义合并规则（这里注意版本问题！！！被坑了）
        ForceNewRowMergeStrategy mergeStrategy = new ForceNewRowMergeStrategy(0, new int[]{0});

        ExcelWriter excelWriter = EasyExcel.write(outputStream)
                .withTemplate(templateStream)
                .excelType(ExcelTypeEnum.XLSX)
                .build();
        //这一行必须加：否则会遇见占位符覆盖的现象，这个比较恶心，会导致最后一行合计无法正常显示
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        WriteSheet writeSheet = EasyExcel.writerSheet()
                //应用合并规则
                .registerWriteHandler(mergeStrategy)
                .registerWriteHandler(columnWidthHandler) // 注册列宽处理器
                .build();
        // 关键：分两次 fill
        // 合计、日期等普通占位符
        excelWriter.fill(dataMap, writeSheet);
        // 列表占位符  如果是多个的话，就会用到这个FillWrapper，我这是为了做演示，就给你加了一下，对应的模板也对应加了一下
        excelWriter.fill(new FillWrapper("data", detailList), fillConfig, writeSheet);
        excelWriter.finish();
    }*/
